package com.example.playnote.fragment

import android.annotation.SuppressLint
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.PagerSnapHelper
import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.chad.library.adapter.base.BaseQuickAdapter
import com.example.playnote.R
import com.example.playnote.activity.login.LoginActivity
import com.example.playnote.activity.ui.ContentActivity
import com.example.playnote.activity.ui.TypeContentActivity
import com.example.playnote.adapter.BannerAdapter
import com.example.playnote.adapter.HomeAdapter
import com.example.playnote.base.BaseFragment
import com.example.playnote.bean.BannerResponse
import com.example.playnote.bean.Constant
import com.example.playnote.bean.HomeListResponse
import com.example.playnote.databinding.FragmentHomeBinding
import com.example.playnote.utils.MMKVUtils
import com.example.playnote.view.CollectArticleView
import com.example.playnote.view.HorizontalRecyclerView
import com.example.playnote.viewModel.HomeViewModel
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import com.example.playnote.bean.Datas
import com.example.playnote.bean.ToastFlag
import com.example.playnote.toasty

class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(),
    CollectArticleView {
    companion object {
        private const val BANNER_TIME = 5000L
    }

    /**
     * check login for SharedPreferences
     */
    private val isLogin: Boolean by lazy {
        MMKVUtils.getBoolean(Constant.LOGIN_KEY) ?: false
    }

    /**
     * Banner
     */
    private var bannerRecyclerView: HorizontalRecyclerView? = null

    /**
     * Data List
     */
    private var homeData: List<Datas>? = null

    /**
     * Banner data
     */
    private var bannerData: BannerResponse? = null

    /**
     * adapter
     */
    private val homeAdapter: HomeAdapter by lazy {
        HomeAdapter(requireContext(), homeData)
    }

    /**
     * Banner RecyclerView adapter
     */
    private val bannerAdapter: BannerAdapter by lazy {
        BannerAdapter(requireContext(), bannerData)
    }

    /**
     * Banner PagerSnapHelper
     */
    private val bannerPagerSnap: PagerSnapHelper by lazy {
        PagerSnapHelper()
    }

    /**
     * LinearLayoutManager
     */
    private val linearLayoutManager: LinearLayoutManager by lazy {
        LinearLayoutManager(activity, LinearLayoutManager.HORIZONTAL, false)
    }

    /**
     * Banner switch job
     */
    private var bannerSwitchJob: Job? = null

    /**
     * save current index
     */
    private var currentIndex = 0

    @SuppressLint("InflateParams")
    override fun initView(savedInstanceState: Bundle?) {
        bannerRecyclerView =
            LayoutInflater.from(requireContext())
                .inflate(R.layout.home_banner, null) as HorizontalRecyclerView?
        mDatabind.swipeRefreshLayout.run {
            isRefreshing = true
            setOnRefreshListener(onRefreshListener)
        }
        mDatabind.recyclerView.run {
            layoutManager = LinearLayoutManager(activity)
            adapter = homeAdapter
        }
        bannerRecyclerView?.run {
            layoutManager = linearLayoutManager
            bannerPagerSnap.attachToRecyclerView(this)
            requestDisallowInterceptTouchEvent(true)
            setOnTouchListener(onTouchListener)
            addOnScrollListener(onScrollListener)
        }
        bannerAdapter.run {
            bindToRecyclerView(bannerRecyclerView)
            onItemClickListener = this@HomeFragment.onBannerItemClickListener
        }
        homeAdapter.run {
            bindToRecyclerView(mDatabind.recyclerView)
            setOnLoadMoreListener(onRequestLoadMoreListener, mDatabind.recyclerView)
            onItemClickListener = this@HomeFragment.onItemClickListener
            onItemChildClickListener = this@HomeFragment.onItemChildClickListener
            addHeaderView(bannerRecyclerView)
            setEmptyView(R.layout.fragment_home_empty)
        }
        mViewModel.getBanner()
        mViewModel.getHomeList()
    }

    override fun createObserver() {
        super.createObserver()
        mViewModel.bannerList.observe(this) {
            if (it.errorCode != 0) {
                getBannerFailed(it.errorMsg)
                return@observe
            }
            it.data ?: let {
                getBannerZero()
                return@observe
            }
            bannerData = it.data
            getBannerSuccess(it.data)
        }
        mViewModel.homeList.observe(this) {
            if (it.errorCode != 0) {
                getHomeListFailed(it.errorMsg)
                return@observe
            }
            val total = it.data.total
            if (total == 0) {
                getHomeListZero()
                return@observe
            }
            if (total < it.data.size) {
                getHomeListSmall(it.data)
                return@observe
            }
            homeData = it.data.datas
            getHomeListSuccess(it.data)
        }
    }

    /**
     * pause banner switch
     */
    override fun onPause() {
        super.onPause()
        cancelSwitchJob()
    }

    /**
     * resume banner switch
     */
    override fun onResume() {
        super.onResume()
        startSwitchJob()
    }

    /**
     * if hidden to cancel, else to start
     */
    override fun onHiddenChanged(hidden: Boolean) {
        super.onHiddenChanged(hidden)
        if (hidden) {
            cancelSwitchJob()
        } else {
            startSwitchJob()
        }
    }

    /**
     * scroll to top
     */
    fun smoothScrollToPosition() = mDatabind.recyclerView.scrollToPosition(0)

    /**
     * refresh
     */
    fun refreshData() {
        mDatabind.swipeRefreshLayout.isRefreshing = true
        homeAdapter.setEnableLoadMore(false)
        cancelSwitchJob()
        mViewModel.getBanner()
        mViewModel.getHomeList()
    }


    /**
     * get Banner Success
     * @param result BannerResponse
     */
    private fun getBannerSuccess(result: BannerResponse) {
        result.let {
            bannerAdapter.replaceData(it)
            startSwitchJob()
        }
    }

    /**
     * get Banner Failed
     * @param errorMessage error message
     */
    private fun getBannerFailed(errorMessage: String?) {
        requireContext().toasty(ToastFlag.ERROR,
            content = errorMessage?:getString(R.string.get_data_error))
    }

    /**
     * get Banner data size equal zero
     */
    private fun getBannerZero() {
        requireContext().toasty(ToastFlag.NORMAL, getString(R.string.get_data_zero))
    }

    private fun getHomeListZero() {
        getBannerZero()
        mDatabind.swipeRefreshLayout.isRefreshing = false
    }

    private fun getHomeListSmall(result: HomeListResponse) {
        result.datas.let {
            homeAdapter.run {
                replaceData(it)
                loadMoreComplete()
                loadMoreEnd()
                setEnableLoadMore(false)
            }
        }
        mDatabind.swipeRefreshLayout.isRefreshing = false
    }

    private fun getHomeListSuccess(result: HomeListResponse) {
        result.datas.let {
            homeAdapter.run {
                // 列表总数
                val total = result.total
                // 当前总数
                if (result.offset >= total || data.size >= total) {
                    loadMoreEnd()
                    return@let
                }
                if (mDatabind.swipeRefreshLayout.isRefreshing) {
                    replaceData(it)
                } else {
                    addData(it)
                }
                loadMoreComplete()
                setEnableLoadMore(true)
            }
        }
        mDatabind.swipeRefreshLayout.isRefreshing = false
    }

    private fun getHomeListFailed(errorMessage: String?) {
        homeAdapter.setEnableLoadMore(false)
        homeAdapter.loadMoreFail()
        requireContext().toasty(ToastFlag.ERROR,
            content = errorMessage?: getString(R.string.get_data_error))
        mDatabind.swipeRefreshLayout.isRefreshing = false
    }

    /**
     * add article success
     * @param result HomeListResponse
     * @param isAdd true add, false remove
     */
    override fun collectArticleSuccess(result: HomeListResponse, isAdd: Boolean) {
        val successMessage = if (isAdd) getString(R.string.bookmark_success)
        else getString(R.string.bookmark_cancel_success)
        requireContext().toasty(ToastFlag.SUCCESS, successMessage)
    }

    /**
     * add article false
     * @param errorMessage error message
     * @param isAdd true add, false remove
     */
    override fun collectArticleFailed(errorMessage: String?, isAdd: Boolean) {
        val failMessage = if (isAdd) getString(R.string.bookmark_failed, errorMessage)
        else getString(R.string.bookmark_cancel_failed, errorMessage)
        requireContext().toasty(ToastFlag.SUCCESS, failMessage)
    }

    /**
     * RefreshListener
     */
    private val onRefreshListener = SwipeRefreshLayout.OnRefreshListener {
        refreshData()
    }

    /**
     * ItemClickListener
     */
    private val onItemClickListener = BaseQuickAdapter.OnItemClickListener { _, _, position ->
        if (homeData?.size != 0) {
            Intent(activity, ContentActivity::class.java).run {
                putExtra(Constant.CONTENT_URL_KEY, homeData!![position].link)
                putExtra(Constant.CONTENT_ID_KEY, homeData!![position].id)
                putExtra(Constant.CONTENT_TITLE_KEY, homeData!![position].title)
                startActivity(this)
            }
        }
    }
    private val onBannerItemClickListener = BaseQuickAdapter.OnItemClickListener { _, _, position ->
        if (bannerData?.size != 0) {
            Intent(activity, ContentActivity::class.java).run {
                putExtra(Constant.CONTENT_URL_KEY, bannerData!![position].url)
                putExtra(Constant.CONTENT_TITLE_KEY, bannerData!![position].title)
                startActivity(this)
            }
        }
    }

    /**
     * ItemChildClickListener
     */
    private val onItemChildClickListener =
        BaseQuickAdapter.OnItemChildClickListener { _, view, position ->
            if (homeData?.size != 0) {
                val data = homeData?.get(position)
                when (view.id) {
                    R.id.homeItemType -> {
                        data?.chapterName ?: let {
                            requireContext().toasty(ToastFlag.ERROR, getString(R.string.type_null))
                            return@OnItemChildClickListener
                        }
                        Intent(activity, TypeContentActivity::class.java).run {
                            putExtra(Constant.CONTENT_TARGET_KEY, true)
                            putExtra(Constant.CONTENT_TITLE_KEY, data.chapterName)
                            putExtra(Constant.CONTENT_CID_KEY, data.chapterId)
                            startActivity(this)
                        }
                    }

                    R.id.homeItemLike -> {
                        if (isLogin) {
                            val collect = data?.collect?:false
                            data?.collect = !collect
                            data?.let { homeAdapter.setData(position, it) }
                            data?.id?.let { mViewModel.collectArticle(it, !collect) }
                        } else {
                            Intent(activity, LoginActivity::class.java).run {
                                startActivityForResult(this, Constant.MAIN_REQUEST_CODE)
                            }
                            requireContext().toasty(ToastFlag.ERROR, getString(R.string.login_please_login))
                        }
                    }
                }
            }
        }

    /**
     * LoadMoreListener
     */
    private val onRequestLoadMoreListener = BaseQuickAdapter.RequestLoadMoreListener {
        val page = homeAdapter.data.size / 20 + 1
        mViewModel.getHomeList(page)
    }

    /**
     * SCROLL_STATE_IDLE to start job
     */
    private val onScrollListener = object : RecyclerView.OnScrollListener() {
        override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
            super.onScrollStateChanged(recyclerView, newState)
            when (newState) {
                RecyclerView.SCROLL_STATE_IDLE -> {
                    currentIndex = linearLayoutManager.findFirstVisibleItemPosition()
                    startSwitchJob()
                }
            }
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        cancelSwitchJob()
    }

    /**
     * ACTION_MOVE to cancel job
     */
    @SuppressLint("ClickableViewAccessibility")
    private val onTouchListener = View.OnTouchListener { _, event ->
        when (event.action) {
            MotionEvent.ACTION_MOVE -> {
                cancelSwitchJob()
            }
        }
        false
    }

    /**
     * get Banner switch job
     */
    private fun getBannerSwitchJob() = lifecycleScope.launch {
        repeat(Int.MAX_VALUE) {
            if (bannerData?.isEmpty() == true) {
                return@launch
            }
            delay(BANNER_TIME)
            currentIndex++
            val index = currentIndex % bannerData?.size!!
            bannerRecyclerView?.smoothScrollToPosition(index)
            currentIndex = index
        }
    }

    /**
     * resume banner switch
     */
    private fun startSwitchJob() = bannerSwitchJob?.run {
        if (!isActive) {
            bannerSwitchJob = getBannerSwitchJob().apply { start() }
        }
    } ?: let {
        bannerSwitchJob = getBannerSwitchJob().apply { start() }
    }

    /**
     * cancel banner switch
     */
    private fun cancelSwitchJob() = bannerSwitchJob?.run {
        if (isActive) {
            cancel()
        }
    }

    override fun lazyLoadData() {
    }
}